import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author Jack Tang
 * @description
 * @create 2023-05-06 13:49
 */
public class VisitorPattern {
    public static void main(String[] args) {
        ObjectStructure os = new ObjectStructure();
        // 将 ConcreteElementA 、 B 都加入数组中
        os.add(new ConcreteElementA());
        os.add(new ConcreteElementB());
        Visitor visitor = new ConcreteVisitorA();
        os.accept(visitor);

        System.out.println("---------------------------------");

        Visitor visitor1 = new ConcreteVisitorB();
        os.accept(visitor1);
    }
}

// 抽象访问者
interface Visitor{
    void visit(ConcreteElementA element);

    void visit(ConcreteElementB element);
}

// 具体访问者 A 类
class ConcreteVisitorA implements Visitor {
    @Override
    public void visit(ConcreteElementA element) {
        System.out.println("具体访问者A访问 --- > " + element.opreationA());
    }

    @Override
    public void visit(ConcreteElementB element) {
        System.out.println("具体访问者A访问 --- > " + element.opreationB());
    }
}

// 具体访问者 B 类
class ConcreteVisitorB implements Visitor {
    @Override
    public void visit(ConcreteElementB element) {
        System.out.println("具体访问者B访问 --- > " + element.opreationB());
    }

    @Override
    public void visit(ConcreteElementA element) {
        System.out.println("具体访问者B访问 --- > " + element.opreationA());
    }
}

// 抽象元素
interface Element{
    void accept(Visitor visitor);
}

// 具体元素 A 类
class ConcreteElementA implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public String opreationA(){
        return "具体元素 A 的操作";
    }
}

// 具体元素 B 类
class ConcreteElementB implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public String opreationB() {
        return "具体元素 B 的操作";
    }
}

// 对象结构角色
class ObjectStructure{
    private List<Element> list = new ArrayList<Element>();

    /*
    * 这段代码的作用是，遍历一个元素列表（list），对每个元素调用其 accept 方法，并把一个访问者对象传给它，以便访问该元素。
    * 具体来说，代码中的 i.next() 返回一个元素对象，强制转换成 Element 类型后，调用其 accept 方法，并把 visitor 对象传进去。
    * 这样，元素就会调用访问者的相应 visit 方法，完成对元素的访问。
    * */
    public void accept(Visitor visitor) {
        Iterator<Element> i = list.iterator();
        //i.hasNext() 方法用于判断当前迭代器 i 是否还有下一个元素，如果有则返回 true，否则返回 false
        while (i.hasNext()) {
            ((Element) i.next()).accept(visitor);
        }
    }

    public void add(Element element) {
        list.add(element);
    }

    public void remove(Element element) {
        list.remove(element);
    }

}